package logic.service;

import dao.*;
import entity.*;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.EntityManager;
import vo.ClassDayVO;
import vo.GroupVO;
import vo.IValueObject;
import vo.SubjectVO;

/**
 *
 * @author Alexander
 */

public class SubjectService implements IService {

    @Override
    public void persist(IValueObject vo, EntityManager em) {
        Subject entity = toEntity(vo, em);

        new SubjectDAO().persist(entity, em);
    }

    @Override
    public IValueObject find(Object id, EntityManager em) {
        Subject s = (Subject) new SubjectDAO().find(id, em);
        if (s != null) {
            return s.toVO();
        } else {
            return null;
        }
    }

    @Override
    public void update(IValueObject vo, EntityManager em) {
        Subject entity = toEntity(vo, em);
        Subject subjectDB = (Subject) new SubjectDAO().find(entity.getCode(), em);
        
        int numGroups = entity.getGroups().size() < subjectDB.getGroups().size() ? entity.getGroups().size() : subjectDB.getGroups().size();
        for (int i = 0; i < numGroups; i++) {
            int numDays = entity.getGroups().get(i).getClassDays().size() < subjectDB.getGroups().get(i).getClassDays().size() ? entity.getGroups().get(i).getClassDays().size() : subjectDB.getGroups().get(i).getClassDays().size();
            for (int j = 0; j < numDays; j++) {
                entity.getGroups().get(i).getClassDays().get(j).setId(subjectDB.getGroups().get(i).getClassDays().get(j).getId());
            }
            if (entity.getGroups().get(i).getClassDays().size() < subjectDB.getGroups().get(i).getClassDays().size()) {
                for (ClassDay dayS : subjectDB.getGroups().get(i).getClassDays()) {
                    boolean exist = false;
                    for (ClassDay dayE : entity.getGroups().get(i).getClassDays()) {
                        if (dayS.getId() == dayE.getId()) {
                            exist = true;
                            break;
                        }
                    }
                    if (!exist) {
                        dayS.setTeacher(null);
                        dayS.getTeacher().getClassDays().remove(dayS);
                        dayS.setGroup(null);
                        dayS.getGroup().getClassDays().remove(dayS);
                        new ClassDayDAO().update(dayS, em);
                        new ClassDayDAO().delete(dayS.getId(), em);
                    }
                }
            }
        }

        new SubjectDAO().update(entity, em);

        if (entity.getGroups().size() < subjectDB.getGroups().size()) {
            for (ClassGroup groupS : subjectDB.getGroups()) {
                boolean exist = false;
                for (ClassGroup groupE : entity.getGroups()) {
                    if (groupS.getId().equals(groupE.getId())) {
                        exist = true;
                        break;
                    }
                }
                if (!exist) {
                    for (ClassDay day : groupS.getClassDays()) {
                        day.setTeacher(null);
                        day.getTeacher().getClassDays().remove(day);
                        day.setGroup(null);
                        day.getGroup().getClassDays().remove(day);
                        new ClassDayDAO().update(day, em);
                        new ClassDayDAO().delete(day, em);
                    }
                    new GroupDAO().delete(groupS.getId(), em);
                }
            }
        }
    }

    @Override
    public void delete(Object id, EntityManager em) {
        new SubjectDAO().delete(id, em);
    }

    public List<SubjectVO> search(Object guess, boolean byCode, EntityManager em) {
        List<Subject> materias = new SubjectDAO().search(guess, byCode, em);
        List<SubjectVO> materiasVo = new ArrayList<>();
        for (Subject m : materias) {
            materiasVo.add(m.toVO());
        }
        return materiasVo;
    }

    @Override
    public List<IValueObject> getList(EntityManager em) {
        List<IValueObject> subjectVO = new ArrayList<>();
        for (Object subject : new SubjectDAO().getList(em)) {
            subjectVO.add(((Subject) subject).toVO());
        }
        return subjectVO;
    }

    private Subject toEntity(IValueObject vo, EntityManager em) {
        Subject entity = new Subject();
        entity.setCode(((SubjectVO) vo).getCode());
        entity.setName(((SubjectVO) vo).getName());
        entity.setCredits(((SubjectVO) vo).getCredits());
        List<ClassGroup> grupos = new ArrayList<>();
        for (GroupVO grupoVO : ((SubjectVO) vo).getGroups()) {
            List<ClassDay> dias = new ArrayList<>();
            for (ClassDayVO diaVO : grupoVO.getClassDays()) {
                ClassDay dia = new ClassDay();
                dia.setDay(diaVO.getDay());
                dia.setHour(diaVO.getHour());
                dia.setSpan(diaVO.getSpan());
                dia.setClassRoom(diaVO.getClassRoom());
                Teacher teacher = (Teacher) new TeacherDAO().find(diaVO.getTeacherId(), em);
                teacher.getClassDays().add(dia);
                dia.setTeacher(teacher);
                dias.add(dia);
            }
            ClassGroup grupo = new ClassGroup();
            grupo.setId(grupoVO.getId());
            grupo.setGroupNumber(grupoVO.getGroupNumber());
            grupo.setClassDays(dias);
            grupo.setSuject(entity);
            for (ClassDay dia : grupo.getClassDays()) {
                dia.setGroup(grupo);
            }
            grupos.add(grupo);
        }
        entity.setGroups(grupos);
        return entity;
    }

    public List<SubjectVO> getSubjectsByUser(String u, EntityManager em) {
        List<Subject> materias = new SubjectDAO().getSubjectsByUser(u, em);
        List<SubjectVO> materiasNom = new ArrayList<>();
        for (Subject m : materias) {
            materiasNom.add(m.toVO());
        }
        return materiasNom;
    }

    public List<SubjectVO> getSubjects(EntityManager em) {
        List<Subject> materias = new SubjectDAO().getSubjects(em);
        List<SubjectVO> materiasNom = new ArrayList<>();
        for (Subject m : materias) {
            materiasNom.add(m.toVO());
        }
        return materiasNom;
    }
}
